import ctypes
import enum
from ctypes import c_void_p, c_int, c_uint8, c_bool, c_char_p, POINTER, Structure
import time

# 加载lib60870库
lib60870 = ctypes.CDLL("./lib60870-C//b1/tools/bin/debug/lib60870.dll")  # 假设库文件名为lib60870.so

# 基础类型定义
CS101_ASDU = c_void_p
IMasterConnection = c_void_p
CS104_Slave = c_void_p
TLSConfiguration = c_void_p
CS104_APCIParameters = c_void_p
CS101_AppLayerParameters = c_void_p
CS101_SlavePlugin = c_void_p
CP56Time2a = c_void_p
CP16Time2a = c_void_p

# 枚举类型封装
class IEC60870_LinkLayerMode(enum.IntEnum):
    IEC60870_LINK_LAYER_BALANCED = 0
    IEC60870_LINK_LAYER_UNBALANCED = 1

class LinkLayerState(enum.IntEnum):
    LL_STATE_IDLE = 0
    LL_STATE_ERROR = 1
    LL_STATE_BUSY = 2
    LL_STATE_AVAILABLE = 3

class CS104_ServerMode(enum.IntEnum):
    CS104_MODE_SINGLE_REDUNDANCY_GROUP = 0
    CS104_MODE_CONNECTION_IS_REDUNDANCY_GROUP = 1
    CS104_MODE_MULTIPLE_REDUNDANCY_GROUPS = 2

class CS104_PeerConnectionEvent(enum.IntEnum):
    CS104_CON_EVENT_CONNECTION_OPENED = 0
    CS104_CON_EVENT_CONNECTION_CLOSED = 1
    CS104_CON_EVENT_EVENT_ACTIVATED = 2
    CS104_CON_EVENT_DEACTIVATED = 3

class IEC60870_5_TypeID(enum.IntEnum):
    M_SP_NA_1 = 1
    M_SP_TA_1 = 2
    M_DP_NA_1 = 3
    # ... 其他类型ID，根据iec60870_common.h补充
    F_SC_NB_1 = 127

class CS101_CauseOfTransmission(enum.IntEnum):
    CS101_COT_PERIODIC = 1
    CS101_COT_BACKGROUND_SCAN = 2
    # ... 其他传输原因，根据iec60870_common.h补充
    CS101_COT_UNKNOWN_IOA = 47

# 结构体封装
class Lib60870VersionInfo(Structure):
    _fields_ = [
        ("major", c_int),
        ("minor", c_int),
        ("patch", c_int)
    ]

class sCS101_AppLayerParameters(Structure):
    _fields_ = [
        ("sizeOfTypeId", c_int),
        ("sizeOfVSQ", c_int),
        ("sizeOfCOT", c_int),
        ("originatorAddress", c_int),
        ("sizeOfCA", c_int),
        ("sizeOfIOA", c_int),
        ("maxSizeOfASDU", c_int)
    ]

class sCS104_APCIParameters(Structure):
    _fields_ = [
        ("k", c_int),
        ("w", c_int),
        ("t0", c_int),
        ("t1", c_int),
        ("t2", c_int),
        ("t3", c_int)
    ]

class sLinkLayerParameters(Structure):
    _fields_ = [
        ("addressLength", c_int),
        ("timeoutForAck", c_int),
        ("timeoutRepeat", c_int),
        ("useSingleCharACK", c_bool),
        ("timeoutLinkState", c_int)
    ]

# 回调函数类型定义
IEC60870_LinkLayerStateChangedHandler = ctypes.CFUNCTYPE(
    None, c_void_p, c_int, c_int)  # 参数: parameter, address, newState

IEC60870_RawMessageHandler = ctypes.CFUNCTYPE(
    None, c_void_p, POINTER(c_uint8), c_int, c_bool)  # 参数: parameter, msg, msgSize, sent

CS101_InterrogationHandler = ctypes.CFUNCTYPE(
    c_bool, c_void_p, IMasterConnection, CS101_ASDU, c_uint8)  # 参数: parameter, connection, asdu, qoi

CS101_ClockSynchronizationHandler = ctypes.CFUNCTYPE(
    c_bool, c_void_p, IMasterConnection, CS101_ASDU, CP56Time2a)  # 参数: parameter, connection, asdu, newTime

CS104_ConnectionRequestHandler = ctypes.CFUNCTYPE(
    c_bool, c_void_p, c_char_p)  # 参数: parameter, ipAddress

CS104_ConnectionEventHandler = ctypes.CFUNCTYPE(
    None, c_void_p, IMasterConnection, c_int)  # 参数: parameter, connection, event

# 函数封装 - iec60870_common.h
lib60870.Lib60870_getLibraryVersionInfo.restype = Lib60870VersionInfo
lib60870.Lib60870_getLibraryVersionInfo.argtypes = []

lib60870.CS101_ASDU_getTypeID.restype = c_int
lib60870.CS101_ASDU_getTypeID.argtypes = [CS101_ASDU]

lib60870.CS101_ASDU_getCOT.restype = c_int
lib60870.CS101_ASDU_getCOT.argtypes = [CS101_ASDU]

lib60870.CS101_ASDU_getCA.restype = c_int
lib60870.CS101_ASDU_getCA.argtypes = [CS101_ASDU]

# 函数封装 - iec60870_slave.h
lib60870.IMasterConnection_sendASDU.restype = c_bool
lib60870.IMasterConnection_sendASDU.argtypes = [IMasterConnection, CS101_ASDU]

lib60870.IMasterConnection_sendACT_CON.restype = c_bool
lib60870.IMasterConnection_sendACT_CON.argtypes = [IMasterConnection, CS101_ASDU, c_bool]

# 函数封装 - cs104_slave.h
lib60870.CS104_Slave_create.restype = CS104_Slave
lib60870.CS104_Slave_create.argtypes = [c_int, c_int]

# lib60870.CS104_Slave_createSecure.restype = CS104_Slave
# lib60870.CS104_Slave_createSecure.argtypes = [c_int, c_int, TLSConfiguration]

lib60870.CS104_Slave_setLocalAddress.restype = None
lib60870.CS104_Slave_setLocalAddress.argtypes = [CS104_Slave, c_char_p]

lib60870.CS104_Slave_setLocalPort.restype = None
lib60870.CS104_Slave_setLocalPort.argtypes = [CS104_Slave, c_int]

lib60870.CS104_Slave_start.restype = None
lib60870.CS104_Slave_start.argtypes = [CS104_Slave]

lib60870.CS104_Slave_stop.restype = None
lib60870.CS104_Slave_stop.argtypes = [CS104_Slave]

lib60870.CS104_Slave_setInterrogationHandler.restype = None
lib60870.CS104_Slave_setInterrogationHandler.argtypes = [CS104_Slave, CS101_InterrogationHandler, c_void_p]

lib60870.CS104_Slave_setClockSyncHandler.restype = None
lib60870.CS104_Slave_setClockSyncHandler.argtypes = [CS104_Slave, CS101_ClockSynchronizationHandler, c_void_p]

lib60870.CS104_Slave_setConnectionRequestHandler.restype = None
lib60870.CS104_Slave_setConnectionRequestHandler.argtypes = [CS104_Slave, CS104_ConnectionRequestHandler, c_void_p]

lib60870.CS104_Slave_setConnectionEventHandler.restype = None
lib60870.CS104_Slave_setConnectionEventHandler.argtypes = [CS104_Slave, CS104_ConnectionEventHandler, c_void_p]

# 高级封装类
class CS104Slave:
    def __init__(self, max_low_prio_queue_size, max_high_prio_queue_size, tls_config=None):
        if tls_config:
            self.slave = lib60870.CS104_Slave_createSecure(
                max_low_prio_queue_size, max_high_prio_queue_size, tls_config)
        else:
            self.slave = lib60870.CS104_Slave_create(
                max_low_prio_queue_size, max_high_prio_queue_size)
        
        self.interrogation_handler = None
        self.clock_sync_handler = None
        self.connection_request_handler = None
        self.connection_event_handler = None

    def set_local_address(self, ip_address):
        lib60870.CS104_Slave_setLocalAddress(self.slave, ip_address.encode('utf-8'))

    def set_local_port(self, port):
        lib60870.CS104_Slave_setLocalPort(self.slave, port)

    def start(self):
        lib60870.CS104_Slave_start(self.slave)

    def stop(self):
        lib60870.CS104_Slave_stop(self.slave)

    def set_interrogation_handler(self, handler):
        self.interrogation_handler = CS101_InterrogationHandler(handler)
        lib60870.CS104_Slave_setInterrogationHandler(
            self.slave, self.interrogation_handler, None)

    def set_clock_sync_handler(self, handler):
        self.clock_sync_handler = CS101_ClockSynchronizationHandler(handler)
        lib60870.CS104_Slave_setClockSyncHandler(
            self.slave, self.clock_sync_handler, None)

    def set_connection_request_handler(self, handler):
        self.connection_request_handler = CS104_ConnectionRequestHandler(handler)
        lib60870.CS104_Slave_setConnectionRequestHandler(
            self.slave, self.connection_request_handler, None)

    def set_connection_event_handler(self, handler):
        self.connection_event_handler = CS104_ConnectionEventHandler(handler)
        lib60870.CS104_Slave_setConnectionEventHandler(
            self.slave, self.connection_event_handler, None)


# 使用示例
def example_usage():
    # 创建从站实例
    slave = CS104Slave(100, 100)
    
    # 设置本地地址和端口
    slave.set_local_address("0.0.0.0")
    slave.set_local_port(2404)
    
    # 定义回调函数
    def interrogation_handler(parameter, connection, asdu, qoi):
        print(f"Received interrogation request, QOI: {qoi}")
        return True
    
    def clock_sync_handler(parameter, connection, asdu, new_time):
        print("Received clock synchronization request")
        return True
    
    def connection_request_handler(parameter, ip_address):
        print(f"Connection request from {ip_address.decode('utf-8')}")
        return True  # 接受连接
    
    def connection_event_handler(parameter, connection, event):
        event_str = CS104_PeerConnectionEvent(event).name
        print(f"Connection event: {event_str}")
    
    # 设置回调函数
    slave.set_interrogation_handler(interrogation_handler)
    slave.set_clock_sync_handler(clock_sync_handler)
    slave.set_connection_request_handler(connection_request_handler)
    slave.set_connection_event_handler(connection_event_handler)
    
    # 启动从站
    slave.start()
    print("CS104 slave started. Press Ctrl+C to stop.")
    
    # 运行一段时间
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        pass
    
    # 停止从站
    slave.stop()
    print("CS104 slave stopped")

if __name__ == "__main__":
    example_usage()